#ifndef _VD_IOCTL_H
#define _VD_IOCTL_H

#include <linux/types.h>

#define VD_MAX_TYPE_NAME 16
#define VD_NAME_LEN 128
#define VD_UUID_LEN 129

struct vd_ioctl {
    /*
     * The version number is made up of three parts:
     * major - no backward or forward compatibility,
     * minor - only backwards compatible,
     * patch - both backwards and forwards compatible.
     *
     * All clients of the ioctl interface should fill in the
     * version number of the interface that they were
     * compiled with.
     *
     * All recognised ioctl commands (ie. those that don't
     * return -ENOTTY) fill out this field, even if the
     * command failed.
     */
    uint32_t version[3];    /* in/out */
    uint32_t data_size;    /* total size of data passed in
                 * including this struct */

    uint32_t data_start;    /* offset to start of data
                 * relative to start of this struct */

    uint32_t target_count;    /* in/out */
    int32_t open_count;    /* out */
    uint32_t flags;        /* in/out */
    uint32_t event_nr;          /* in/out */
    uint32_t padding;

    uint32_t id;        /* raid id in/out */

    char name[VD_NAME_LEN];    /* device name */
    char uuid[VD_UUID_LEN];    /* unique identifier for
                 * the block device */
};

struct vd_target_spec {
    uint64_t sector_start;
    uint64_t length;
    int32_t status;        /* used when reading from kernel only */

    /*
     * Location of the next dm_target_spec.
     * - When specifying targets on a DM_TABLE_LOAD command, this value is
     *   the number of bytes from the start of the "current" dm_target_spec
     *   to the start of the "next" dm_target_spec.
     * - When retrieving targets on a DM_TABLE_STATUS command, this value
     *   is the number of bytes from the start of the first dm_target_spec
     *   (that follows the dm_ioctl struct) to the start of the "next"
     *   dm_target_spec.
     */
    uint32_t next;

    char target_type[VD_MAX_TYPE_NAME];

    /*
     * Parameter string starts immediately after this object.
     * Be careful to add padding after string to ensure correct
     * alignment of subsequent dm_target_spec.
     */
};

enum {
    /* Top level cmds */
    VD_VERSION_CMD = 0,
    VD_REMOVE_ALL_CMD,
    VD_LIST_DEVICES_CMD,

    /* device level cmds */
    VD_DEV_CREATE_CMD,
    VD_DEV_REMOVE_CMD,
    VD_DEV_RENAME_CMD,
    VD_DEV_SUSPEND_CMD,
    VD_DEV_STATUS_CMD,
    VD_DEV_WAIT_CMD,

    /* Table level cmds */
    VD_TABLE_LOAD_CMD,
    VD_TABLE_CLEAR_CMD,
    VD_TABLE_DEPS_CMD,
    VD_TABLE_STATUS_CMD,

    /* Added later */
    VD_LIST_VERSIONS_CMD,
    VD_TARGET_MSG_CMD,
    VD_DEV_SET_GEOMETRY_CMD
};

#define VD_IOCTL 0xfd

#define VD_VERSION       _IOWR(VD_IOCTL, VD_VERSION_CMD, struct vd_ioctl)
#define VD_REMOVE_ALL    _IOWR(VD_IOCTL, VD_REMOVE_ALL_CMD, struct vd_ioctl)
#define VD_LIST_DEVICES  _IOWR(VD_IOCTL, VD_LIST_DEVICES_CMD, struct vd_ioctl)

#define VD_DEV_CREATE    _IOWR(VD_IOCTL, VD_DEV_CREATE_CMD, struct vd_ioctl)
#define VD_DEV_REMOVE    _IOWR(VD_IOCTL, VD_DEV_REMOVE_CMD, struct vd_ioctl)
#define VD_DEV_RENAME    _IOWR(VD_IOCTL, VD_DEV_RENAME_CMD, struct vd_ioctl)
#define VD_DEV_SUSPEND   _IOWR(VD_IOCTL, VD_DEV_SUSPEND_CMD, struct vd_ioctl)
#define VD_DEV_STATUS    _IOWR(VD_IOCTL, VD_DEV_STATUS_CMD, struct vd_ioctl)
#define VD_DEV_WAIT      _IOWR(VD_IOCTL, VD_DEV_WAIT_CMD, struct vd_ioctl)

#define VD_TABLE_LOAD    _IOWR(VD_IOCTL, VD_TABLE_LOAD_CMD, struct vd_ioctl)
#define VD_TABLE_CLEAR   _IOWR(VD_IOCTL, VD_TABLE_CLEAR_CMD, struct vd_ioctl)
#define VD_TABLE_DEPS    _IOWR(VD_IOCTL, VD_TABLE_DEPS_CMD, struct vd_ioctl)
#define VD_TABLE_STATUS  _IOWR(VD_IOCTL, VD_TABLE_STATUS_CMD, struct vd_ioctl)

#define VD_LIST_VERSIONS _IOWR(VD_IOCTL, VD_LIST_VERSIONS_CMD, struct vd_ioctl)

#define VD_TARGET_MSG     _IOWR(VD_IOCTL, VD_TARGET_MSG_CMD, struct vd_ioctl)
#define VD_DEV_SET_GEOMETRY    _IOWR(VD_IOCTL, VD_DEV_SET_GEOMETRY_CMD, struct vd_ioctl)

#define VD_READONLY_FLAG    (1 << 0) /* In/Out */
#define VD_SUSPEND_FLAG        (1 << 1) /* In/Out */
#define VD_PERSISTENT_DEV_FLAG    (1 << 3) /* In */

/*
 * Flag passed into ioctl STATUS command to get table information
 * rather than current status.
 */
#define VD_STATUS_TABLE_FLAG    (1 << 4) /* In */

/*
 * Flags that indicate whether a table is present in either of
 * the two table slots that a device has.
 */
#define VD_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
#define VD_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */

/*
 * Indicates that the buffer passed in wasn't big enough for the
 * results.
 */
#define VD_BUFFER_FULL_FLAG    (1 << 8) /* Out */

/*
 * This flag is now ignored.
 */
#define VD_SKIP_BDGET_FLAG    (1 << 9) /* In */

/*
 * Set this to avoid attempting to freeze any filesystem when suspending.
 */
#define VD_SKIP_LOCKFS_FLAG    (1 << 10) /* In */

#endif

